import * as THREE from 'three'
import { useEffect, useState } from 'react'
import './App.css'
import * as dat from 'dat.gui'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import Stats from "stats.js"

const App = () => {
  useEffect(() => {
    let mixer: any
    const clock = new THREE.Clock()

    const stats = new Stats();
    document.body.appendChild(stats.dom);

    stats.showPanel(0);
    const control = new dat.GUI()

    const scene = new THREE.Scene()

    const axes = new THREE.AxesHelper(200)
    scene.add(axes)

    /** 相机设置 */
    const width = window.innerWidth //窗口宽度
    const height = window.innerHeight //窗口高度
    const k = width / height //窗口宽高比
    const s = 5 //三维场景显示范围控制系数，系数越大，显示的范围越大
    //创建相机对象
    const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 0.1, 1000)
    camera.position.set(50, 20, 50) //设置相机位置
    camera.lookAt(scene.position) //设置相机方向(指向的场景对象)

    /** 创建渲染器对象 */
    const renderer = new THREE.WebGLRenderer()
    renderer.setSize(width, height) //设置渲染区域尺寸
    renderer.setClearColor(0xAF9565, 1); //设置背景颜色
    document.body.appendChild(renderer.domElement) //body元素中插入canvas对象

    renderer.shadowMap.enabled = true

    const controls = new OrbitControls(camera, renderer.domElement)
    controls.update()

    light(scene, control)

    // 增加地面
    const groundGeom = new THREE.PlaneGeometry(512, 512, 2, 2)
    const groundMaterial = new THREE.MeshStandardMaterial({ color: 0xefefef })
    const groundMesh = new THREE.Mesh(groundGeom, groundMaterial)
    groundMesh.receiveShadow = true
    groundMesh.rotation.x = - Math.PI / 2
    groundMesh.position.y = 0
    scene.add(groundMesh)
    
    try{
      const loader = new GLTFLoader();

      loader.load( 'src/test.glb', function ( gltf ) {
        gltf.scene.scale.set(4, 4, 4);
        console.log(gltf.scene);
        

        mixer = new THREE.AnimationMixer(gltf.scene)
        mixer.clipAction(gltf.animations[0]).play()

        gltf.scene.traverse(function(object: any) {
          if (object.isMesh) {
            object.castShadow = true
          }
        })
        scene.add(gltf.scene );
      }, undefined, function ( error ) {
      
        console.error( error );
      
      } );
        
    }catch(e){
        console.error('解析失败',e);
    }



    const renderScene = () => {
      if (mixer) mixer.update(clock.getDelta())

      controls.update()
      stats.update();
      requestAnimationFrame(renderScene)
      renderer.render(scene, camera)
    }

    renderScene()
  }, [])

  const light = (scene: THREE.Scene, control: dat.GUI) => {
    const folder = control.addFolder('基础属性')

    // 环境光，没有特定的方向
    const ambLightObj = {
      visible: true,
      intensity: 0.7,
      color: 0xe0e0e0
    }
    const ambientLight = new THREE.AmbientLight(ambLightObj.color)
    ambientLight.intensity = ambLightObj.intensity
    scene.add(ambientLight)

    folder.addColor(ambLightObj, 'color').name('环境灯颜色').onChange(function (e) {
      ambientLight.color = new THREE.Color(e)
    })
    folder.add(ambLightObj, 'visible', -200, 200).name('环境灯显示').onChange(function (e) {
      ambientLight.visible = e
    })
    folder.add(ambLightObj, 'intensity', 0, 5).name('环境灯强度').onChange(function (e) {
      ambientLight.intensity = e
    })
    
    const drtLightObj = {
      x: 200,
      y: 200,
      z: 140,
      visible: true,
      intensity: 0.5,
      color: 0xffffff
    }
    const directionalLight = new THREE.DirectionalLight( drtLightObj.color, drtLightObj.intensity );
    directionalLight.position.set(drtLightObj.x, drtLightObj.y, drtLightObj.z)
    directionalLight.shadow.mapSize.width = 1024
    directionalLight.shadow.mapSize.height = 1024
    directionalLight.visible = true
    scene.add( directionalLight );

    folder.addColor(drtLightObj, 'color').onChange(function (e) {
      directionalLight.color = new THREE.Color(e)
    })
    folder.add(drtLightObj, 'x', -200, 200).onChange(function (e) {
      directionalLight.position.x = e
    })
    folder.add(drtLightObj, 'y', -200, 200).onChange(function (e) {
      directionalLight.position.y = e
    })
    folder.add(drtLightObj, 'z', -200, 200).onChange(function (e) {
      directionalLight.position.z = e
    })
    folder.add(drtLightObj, 'visible').onChange(function (e) {
      directionalLight.visible = e
    })
    folder.add(drtLightObj, 'intensity', 0, 20).onChange(function (e) {
      directionalLight.intensity = e
    })
  }

  return <div className="App"></div>
}

export default App
